﻿using Sgr.AspNetCore.ActionFilters.Permissions;
using Sgr.Security;
using Microsoft.AspNetCore.Mvc;

namespace Microsoft.AspNetCore.Builder
{
    public static class MinimalApiAuthorizationExtensions
    {
        /// <summary>
        /// 无参数版本：仅进行认证检查
        /// </summary>
        public static RouteHandlerBuilder RequirePermission(this RouteHandlerBuilder builder)
        {
            return builder.RequirePermission(
                permissions: Array.Empty<string>(),
                logicMode: PermissionLogicMode.And,
                resultType: CheckPermissionResultType.Json
            );
        }

        /// <summary>
        /// 单权限版本
        /// </summary>
        public static RouteHandlerBuilder RequirePermission(
            this RouteHandlerBuilder builder,
            string permissionSystemName)
        {
            if (string.IsNullOrWhiteSpace(permissionSystemName))
                throw new ArgumentException("权限名称不能为空", nameof(permissionSystemName));

            return builder.RequirePermission(
                permissions: new[] { permissionSystemName },
                logicMode: PermissionLogicMode.And,
                resultType: CheckPermissionResultType.Json
            );
        }

        /// <summary>
        /// 多权限版本（可变参数，与逻辑）
        /// </summary>
        public static RouteHandlerBuilder RequirePermission(
            this RouteHandlerBuilder builder,
            params string[] permissionSystemNames)
        {
            return builder.RequirePermission(
                permissions: permissionSystemNames,
                logicMode: PermissionLogicMode.And,
                resultType: CheckPermissionResultType.Json
            );
        }

        /// <summary>
        /// 便利版本：支持显式指定逻辑模式的可变参数版本
        /// </summary>
        public static RouteHandlerBuilder RequirePermission(
            this RouteHandlerBuilder builder,
            PermissionLogicMode logicMode,
            params string[] permissionSystemNames)
        {
            return builder.RequirePermission(
                permissions: permissionSystemNames,
                logicMode: logicMode,
                resultType: CheckPermissionResultType.Json
            );
        }

        /// <summary>
        /// 完整版本：指定多个权限名称、逻辑模式和返回类型
        /// </summary>
        public static RouteHandlerBuilder RequirePermission(
            this RouteHandlerBuilder builder,
            string[] permissions,
            PermissionLogicMode logicMode,
            CheckPermissionResultType resultType)
        {
            // 验证权限名称数组
            ValidatePermissionNames(permissions);

            builder.RequireAuthorization();

            builder.AddEndpointFilter(async (context, next) =>
            {
                var httpContext = context.HttpContext;

                try
                {
                    // 1. 先检查是否已认证
                    if (httpContext.User.Identity is not { IsAuthenticated: true })
                    {
                        LogPermissionCheck(httpContext, permissions, logicMode, false, "用户未认证");
                        var problemDetails = httpContext.CreateUnauthorizedProblemDetails();
                        return new UnauthorizedObjectResult(problemDetails);
                    }

                    // 2. 如果没有指定权限，则认证通过即可
                    if (permissions.Length == 0)
                    {
                        //LogPermissionCheck(httpContext, permissions, logicMode, true, "无需权限验证");
                        return await next(context);
                    }

                    // 3. 根据逻辑模式进行权限检查
                    var functionPermissionGrantingService = httpContext.RequestServices
                        .GetRequiredService<IFunctionPermissionGrantingService>();

                    bool hasPermission = await CheckPermissionAttribute.CheckPermissionsByLogicMode(
                        functionPermissionGrantingService,
                        httpContext.User,
                        permissions,
                        logicMode);

                    if (hasPermission)
                    {
                        //LogPermissionCheck(httpContext, permissions, logicMode, true, "权限验证通过");
                        return await next(context);
                    }

                    LogPermissionCheck(httpContext, permissions, logicMode, false, "权限验证失败");

                    // 4. 返回权限不足响应
                    return resultType switch
                    {
                        CheckPermissionResultType.Json => CheckPermissionAttribute.CreateAccessDeniedJsonResult(httpContext, permissions, logicMode),
                        CheckPermissionResultType.Html => CheckPermissionAttribute.CreateAccessDeniedViewResult(),
                        _ => Results.Forbid()
                    };
                }
                catch (Exception ex)
                {
                    httpContext.RequestServices
                        .GetService<ILogger<CheckPermissionAttribute>>()
                        ?.LogError(ex, "权限检查过程中发生异常");

                    return Results.StatusCode(StatusCodes.Status500InternalServerError);
                }
            });

            return builder;
        }

        /// <summary>
        /// 验证权限名称数组
        /// </summary>
        private static void ValidatePermissionNames(string[] permissionSystemNames)
        {
            if (permissionSystemNames == null)
                throw new ArgumentException("权限名称数组不能为空", nameof(permissionSystemNames));
            if (permissionSystemNames.Any(string.IsNullOrWhiteSpace))
                throw new ArgumentException("权限名称不能为 null 或空字符串", nameof(permissionSystemNames));
        }

        /// <summary>
        /// 记录权限检查日志
        /// </summary>
        private static void LogPermissionCheck(HttpContext httpContext, string[] permissions, PermissionLogicMode logicMode, bool isGranted, string reason)
        {
            var logger = httpContext.RequestServices.GetService<ILogger<CheckPermissionAttribute>>();
            if (logger == null) return;

            var user = httpContext.User.Identity?.Name ?? "anonymous";
            var path = httpContext.Request.Path;
            var method = httpContext.Request.Method;
            var logicModeText = logicMode == PermissionLogicMode.And ? "AND" : "OR";

            if (!isGranted)
            {
                logger.LogWarning(
                    "用户 {User} {Method} {Path} 权限检查失败。需要权限: {Permissions}，逻辑模式: {LogicMode}，失败原因: {Reason}",
                    user, method, path, string.Join(", ", permissions), logicModeText, reason);
            }
            else
            {
                logger.LogInformation(
                    "用户 {User} {Method} {Path} 权限检查通过。逻辑模式: {LogicMode}，原因: {Reason}",
                    user, method, path, logicModeText, reason);
            }
        }
    }
}